package twi.query.template;

import java.awt.Component;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.FileOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.JCheckBox;
import javax.swing.JPanel;

import jtools.gui.DefaultLayoutNode;
import jtools.gui.TreeLayoutNode;
import twi.Utils;
import twi.filter.DropAnonFilter;
import twi.query.template.view.ClassPropertiePanel;
import twi.query.template.view.IndividualPropertiePanel;
import twi.query.template.view.IndividualSinglePropertyPanel;
import twi.query.template.view.TemplateClassPanel;
import twi.query.template.view.TemplateMainView;
import twi_project.TWI;

import com.hp.hpl.jena.ontology.DatatypeProperty;
import com.hp.hpl.jena.ontology.Individual;
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntProperty;
import com.hp.hpl.jena.ontology.OntResource;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;

public class ClassNode extends DefaultLayoutNode implements TemplateNode, Serializable {

	class DomainProperty implements Serializable{
		boolean isDomain = true;
		String prop = null;
	}
	private ArrayList<String> ontClassList;
	private Template template = null;
	private TemplateClassPanel panel = null;
	transient private Property propertie;
	private String propertie_uri = null;
	private boolean isIndividual = false;
	private ArrayList<DomainProperty> propertieList = new ArrayList<DomainProperty>();
	private ArrayList<String> propertieStringList = new ArrayList<String>();
	private boolean init;
	
	private boolean optional = false;
	private boolean editable = false;
	private boolean showResult = true;
	private boolean asVariable;
	
	public ClassNode(){
		super();
	}
	public void write(FileOutputStream fout){
		
	}
	public void writeString(FileOutputStream fout, String s){
		
	}
	
	
	public ClassNode(TreeLayoutNode par, ArrayList<String> list, Template template, Property prop) {
		super(par);
		this.ontClassList = list;
		Collections.sort(this.ontClassList);
		this.template = template;
		this.propertie = prop;
		if (prop != null)
			this.propertie_uri = prop.getURI();
	}


	@Override
	public void addChild(OntResource resource) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setMaximized() {
		if (this.panel != null){
			this.template.minimizeAll();
			this.panel.setMaximized(true);
		}
	}

	@Override
	public void setMinimized() {
		if (this.panel != null)
			this.panel.setMaximized(false);
	}

	@Override
	public Component getComponent() {
		if (this.panel != null)
			return this.panel;
		createPanel();
		return this.panel;
	}

	private void createPanel() {
		this.panel = new TemplateClassPanel(this);
		for (int i = 0; i < this.ontClassList.size(); i++){
			this.panel.addToComboBox(this.ontClassList.get(i));
		}
		this.panel.setVariableName(this.panel.getClassName());
	}

	public void itemChanged(String name) {
		if (!init)
			this.deepRemove();
		String vn = NameFactory.createNameFromClassName(name);
		OntClass cl = TWI.getInstance().getOntologieModel().getOntClass(name);
		if (cl != null){
			JPanel panel = createClassPanel(cl);
			this.panel.setVariableName(vn);
			this.panel.setHidePanel(panel);
			this.template.doLayout();
			return ;
		}
		Individual in = TWI.getInstance().getOntologieModel().getIndividual(name);
		if (in != null || name.equals(Template.INDIVIDUAL)){
			JPanel panel = null; 
			if (in != null)
				panel = null;//createIndividualPanel(in);
			else
				panel = createAnonIndividual();
			this.panel.setVariableName(vn);
			this.panel.setHidePanel(panel);
			this.template.doLayout();
			this.isIndividual = true;
			return ;
		}
		Property propertie = null;
		try{
			propertie = TWI.getInstance().getOntologieModel().getProperty(propertie_uri);
			if (propertie instanceof OntProperty){
				OntProperty prop = (OntProperty) propertie;
				if (prop.isDatatypeProperty()){
					DatatypeProperty dataProp = prop.asDatatypeProperty();
					IndividualSinglePropertyPanel ispp = new IndividualSinglePropertyPanel(propertie.getLocalName(), new ArrayList<String>());
					ispp.setDatatype(true);
					ArrayList<IndividualSinglePropertyPanel> l = new ArrayList<IndividualSinglePropertyPanel>();
					l.add(ispp);
					JPanel panel = new IndividualPropertiePanel(this, l);
					this.panel.setVariableName((prop.getLocalName()));
					this.panel.setHidePanel(panel);
					this.template.doLayout();
					this.panel.setVariableName(vn);
					this.panel.enableSetName = false;
					return ;
				}
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
	}

	private JPanel createAnonIndividual() {
		ClassNode parent = (ClassNode) this.getParent();
		OntClass parClass = parent.getSelectedClass();
		if (parClass == null)
			return null;
		ArrayList<IndividualSinglePropertyPanel> panellist = new ArrayList<IndividualSinglePropertyPanel>();
		List<OntProperty> propList = Utils.getPropertyList(parClass, true, true);
		for (int i = 0; i < propList.size(); i++){
			OntProperty p = propList.get(i);
			ArrayList<OntClass> domainClasses = Utils.listClasses(p.getRange(), true, true);
			ArrayList<String> wordList = new ArrayList<String>();
			for (int j = 0; j < domainClasses.size(); j++)
				wordList.add(Utils.getLocalName(domainClasses.get(j)));
			panellist.add(new IndividualSinglePropertyPanel(p.getLocalName(), wordList));
		}
		this.isIndividual = true;
		return new IndividualPropertiePanel(this, panellist);
	}


	public OntClass getSelectedClass() {
		return TWI.getInstance().getOntologieModel().getOntClass(this.panel.getClassName());
	}
	public Individual getSelectedIndividual() {
		return TWI.getInstance().getOntologieModel().getIndividual(this.panel.getClassName());
	}

	private JPanel createIndividualPanel(Individual in) {
		StmtIterator iter = in.listProperties();
		ArrayList<IndividualSinglePropertyPanel> panelList = new ArrayList<IndividualSinglePropertyPanel>();
		while(iter.hasNext()){
			Statement stmpt = iter.nextStatement();
			Property p = stmpt.getPredicate();
			ArrayList<String> wordList = new ArrayList<String>();
			panelList.add(new IndividualSinglePropertyPanel(p.getLocalName(), wordList));
		}
		IndividualPropertiePanel panel = new IndividualPropertiePanel(this, panelList);
		this.isIndividual  = true;
		return panel;
	}

	private JPanel createClassPanel(OntClass cl) {
		ClassPropertiePanel panel = new ClassPropertiePanel(this);
		List<OntProperty> propList = Utils.getPropertyList(cl, true, true);
		ArrayList<JCheckBox> cbList = new ArrayList<JCheckBox>();
		for (int i =0 ; i < propList.size(); i++){
			final OntProperty prop = (OntProperty) propList.get(i);
			String n = prop.getLocalName();
			if (prop.listRange().filterDrop(new DropAnonFilter()).toList().isEmpty())
				continue;
			final boolean isDomain = Utils.isDomain(cl, prop);
			if (!haveProperty(prop)){
				DomainProperty dp = new DomainProperty();
				dp.isDomain = isDomain;
				dp.prop = prop.getURI();
				this.propertieList.add(dp);
			}
			final JCheckBox cb = new JCheckBox(n);
			cb.addItemListener(new ItemListener(){
				@Override
				public void itemStateChanged(ItemEvent e) {
					updateNodes(prop, cb.isSelected(), isDomain);
				}
			});
			cbList.add(cb);
		}
		panel.setComboxes(cbList);
		return panel;
	}

	private boolean haveProperty(OntProperty prop) {
		for (int i = 0; i < propertieList.size(); i++)
			if (this.propertieList.get(i).prop.equals(prop.getURI()))
				return true;
		return false;
	}


	protected void updateNodes(OntProperty prop, boolean newNode, boolean isDomain) {
		List list = prop.listRange().filterDrop(new DropAnonFilter()).toList();
		this.template.updateNodes(this, prop, newNode, isDomain);
	}

	public Property getPropertie() {
		return TWI.getInstance().getOntologieModel().getProperty(propertie_uri);
	}

	public void createIndividual() {
		String className = this.panel.getClassName();
		this.template.createIndividualNode(this, className);
	}

	public void delete() {
		this.deepRemove();
		if (this.getParent() == null)
			this.template.removeRoot(this);
		else
			this.getParent().removeChild(this);
		this.template.doLayout();		
	}


	public String getVariableName() {
		return this.panel.getVariableName();
	}


	public TemplateClassPanel getPanel() {
		return this.panel;
	}


	public boolean isDatatypeOnly() {
		Property propertie = getPropertie();
		if (propertie instanceof OntProperty){
			return ((OntProperty)propertie).isDatatypeProperty();
		}
		return false;
	}


	public boolean isIndividual() {
		return this.isIndividual;
	}


	public boolean isDomainProperty(Property prop) {
		for (int i = 0; i < this.propertieList.size(); i++)
			if (this.propertieList.get(i).prop.equals(prop.getURI()))
				return this.propertieList.get(i).isDomain;
//		throw new IllegalArgumentException("Unknown Property "+prop);
		return true;
	}
	public void init(TemplateMainView mv) {
		this.init = true;
		mv.getTreePanel().add(this);
		for (int i = 0; i < this.getChildCount(); i++)
			((ClassNode)this.getChild(i)).init(mv);
		this.init = false;
	}
	public void setOptional(boolean selected) {
		this.optional = selected;
	}
	public void setEditable(boolean selected) {
		this.editable = selected;
	}
	public void setShowResult(boolean selected) {
		this.showResult = selected;
	}
	public boolean isOptional() {
		return optional;
	}
	public boolean isEditable() {
		return editable;
	}
	public boolean isShowResult() {
		return showResult;
	}
	public void setAsVariable(boolean selected) {
		this.asVariable = selected;
		
	}
	public boolean isAsVariable() {
		return asVariable;
	}



	
	
	
	
}
